home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / ASSEMBLE / H145.ZIP / ASXXXX_3.ZIP / LKMAIN.C < prev    next >
C/C++ Source or Header  |  1990-07-18  |  9KB  |  559 lines

  1. /* lkmain.c */
  2.  
  3. /*
  4.  * (C) Copyright 1989,1990
  5.  * All Rights Reserved
  6.  *
  7.  * Alan R. Baldwin
  8.  * 721 Berkeley St.
  9.  * Kent, Ohio  44240
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <alloc.h>
  15. #include "aslink.h"
  16.  
  17. VOID
  18. main(argc, argv)
  19. char *argv[];
  20. {
  21.     register char *p;
  22.     register c, i;
  23.     FILE *afile();
  24.  
  25.     fprintf(stdout, "\n");
  26.  
  27.     pflag = 1;
  28.     startp = (struct lfile *) new (sizeof (struct lfile));
  29.  
  30.     for (i=1; i<argc; ++i) {
  31.         p = argv[i];
  32.         if (*p == '-') {
  33.             while (ctype[c = *(++p)] & LETTER) {
  34.                 switch(c) {
  35.  
  36.                 case 'c':
  37.                 case 'C':
  38.                     startp->f_type = F_STD;
  39.                     break;
  40.  
  41.                 case 'f':
  42.                 case 'F':
  43.                     startp->f_type = F_LNK;
  44.                     break;
  45.                     
  46.                 case 'n':
  47.                 case 'N':
  48.                     pflag = 0;
  49.                     break;
  50.  
  51.                 case 'p':
  52.                 case 'P':
  53.                     pflag = 1;
  54.                     break;
  55.  
  56.                 default:
  57.                     usage();
  58.                 }
  59.             }
  60.         } else {
  61.             if (startp->f_type == F_LNK) {
  62.                 startp->f_idp = p;
  63.             }
  64.         }
  65.     }
  66.     if (startp->f_type == NULL)
  67.         usage();
  68.     if (startp->f_type == F_LNK && startp->f_idp == NULL)
  69.         usage();
  70.  
  71.     cfp = NULL;
  72.     sfp = NULL;
  73.     filep = startp;
  74.     while (1) {
  75.         ip = ib;                    
  76.         if (getline() == 0)
  77.             break;
  78.         if (pflag && sfp != stdin)
  79.             fprintf(stdout, "%s\n", ip);
  80.         if (*ip == NULL || parse())
  81.             break;
  82.     }
  83.     fclose(sfp);
  84.     if (linkp == NULL)
  85.         usage();
  86.  
  87.     syminit();
  88.     for (pass=0; pass<2; ++pass) {
  89.         cfp = NULL;
  90.         sfp = NULL;
  91.         filep = linkp;
  92.         hp = NULL;
  93.         radix = 10;
  94.  
  95.         while (getline()) {
  96.             ip = ib;
  97.             link();
  98.         }
  99.         if (pass == 0) {
  100.             /*
  101.              * Set area base addresses.
  102.              */
  103.             setbas();
  104.             /*
  105.              * Link all area addresses.
  106.              */
  107.             lnkarea();
  108.             /*
  109.              * Process global definitions.
  110.              */
  111.             setgbl();
  112.             /*
  113.              * Check for undefined globals.
  114.              */
  115.             symdef(stderr);
  116.             /*
  117.              * Output Link Map.
  118.              */
  119.             if (mflag)
  120.                 map();
  121.             /*
  122.              * Open output file
  123.              */
  124.             if (oflag == 1)
  125.                 ofp = afile(linkp->f_idp, "IHX", 1);
  126.             if (oflag == 2)
  127.                 ofp = afile(linkp->f_idp, "S19", 1);
  128.         } else {
  129.             reloc('E');
  130.         }
  131.     }
  132. }
  133.  
  134. VOID
  135. link()
  136. {
  137.     register c;
  138.  
  139.     if ((c=endline()) == 0) { return; }
  140.     switch (c) {
  141.  
  142.     case 'X':
  143.         radix = 16;
  144.         break;
  145.  
  146.     case 'D':
  147.         radix = 10;
  148.         break;
  149.  
  150.     case 'Q':
  151.         radix = 8;
  152.         break;
  153.  
  154.     case 'H':
  155.         if (pass == 0) {
  156.             newhead();
  157.         } else {
  158.             if (hp == 0) {
  159.                 hp = headp;
  160.             } else {
  161.                 hp = hp->h_hp;
  162.             }
  163.         }
  164.         sdp.s_area = NULL;
  165.         sdp.s_areax = NULL;
  166.         sdp.s_addr = 0;
  167.         break;
  168.  
  169.     case 'M':
  170.         if (pass == 0)
  171.             module();
  172.         break;
  173.  
  174.     case 'A':
  175.         if (pass == 0)
  176.             newarea();
  177.         if (sdp.s_area == NULL) {
  178.             sdp.s_area = areap;
  179.             sdp.s_areax = areap->a_axp;
  180.             sdp.s_addr = 0;
  181.         }
  182.         break;
  183.  
  184.     case 'S':
  185.         if (pass == 0)
  186.             newsym();
  187.         break;
  188.  
  189.     case 'T':
  190.     case 'R':
  191.     case 'P':
  192.         if (pass == 0)
  193.             break;
  194.         reloc(c);
  195.         break;
  196.  
  197.     default:
  198.         break;
  199.     }
  200.     if (c == 'X' || c == 'D' || c == 'Q') {
  201.         if ((c = get()) == 'H') {
  202.             hilo = 1;
  203.         } else
  204.         if (c == 'L') {
  205.             hilo = 0;
  206.         }
  207.     }
  208. }
  209.  
  210. VOID
  211. map()
  212. {
  213.     register i;
  214.     register struct head *hdp;
  215.  
  216.     /*
  217.      * Open Map File
  218.      */
  219.     mfp = afile(linkp->f_idp, "MAP", 1);
  220.     /*
  221.      * Output Map Area Lists
  222.      */
  223.     page = 0;
  224.     lop  = NLPP;
  225.     slew(mfp);
  226.     ap = areap;
  227.     while (ap) {
  228.         lstarea(ap);
  229.         ap = ap->a_ap;
  230.     }
  231.     /*
  232.      * List Linked Files
  233.      */
  234.     newpag(mfp);
  235.     fprintf(mfp, "\nFiles Linked      [ module(s) ]\n\n");
  236.     hdp = headp;
  237.     filep = linkp;
  238.     while (filep) {
  239.         fprintf(mfp, "%-16s", filep->f_idp);
  240.         i = 0;
  241.         while (hdp->h_lfile == filep) {
  242.             if (i % 5) {
  243.                 fprintf(mfp, ", %8.8s", hdp->m_id);
  244.             } else {
  245.                 if (i) {
  246.                 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
  247.                 } else {
  248.                 fprintf(mfp, "  [ %8.8s", hdp->m_id);
  249.                 }
  250.             }
  251.             hdp = hdp->h_hp;
  252.             i++;
  253.         }
  254.         if (i)
  255.             fprintf(mfp, " ]");
  256.         fprintf(mfp, "\n");
  257.         filep = filep->f_flp;
  258.     }
  259.     /*
  260.      * List Base Address Definitions
  261.      */
  262.     if (basep) {
  263.         newpag(mfp);
  264.         fprintf(mfp, "\nUser Base Address Definitions\n\n");
  265.         bsp = basep;
  266.         while (bsp) {
  267.             fprintf(mfp, "%s\n", bsp->b_strp);
  268.             bsp = bsp->b_base;
  269.         }
  270.     }
  271.     /*
  272.      * List Global Definitions
  273.      */
  274.     if (globlp) {
  275.         newpag(mfp);
  276.         fprintf(mfp, "\nUser Global Definitions\n\n");
  277.         gsp = globlp;
  278.         while (gsp) {
  279.             fprintf(mfp, "%s\n", gsp->g_strp);
  280.             gsp = gsp->g_globl;
  281.         }
  282.     }
  283.     fprintf(mfp, "\n\f");
  284.     symdef(mfp);
  285. }
  286.  
  287. int
  288. parse()
  289. {
  290.     register c;
  291.     char fid[NINPUT];
  292.  
  293.     while ((c = getnb()) != 0) {
  294.         if ( c == '-') {
  295.             while (ctype[c=get()] & LETTER) {
  296.                 switch(c) {
  297.  
  298.                 case 'i':
  299.                 case 'I':
  300.                     oflag = 1;
  301.                     break;
  302.  
  303.                 case 's':
  304.                 case 'S':
  305.                     oflag = 2;
  306.                     break;
  307.  
  308.                 case 'm':
  309.                 case 'M':
  310.                     ++mflag;
  311.                     break;
  312.  
  313.                 case 'x':
  314.                 case 'X':
  315.                     xflag = 0;
  316.                     break;
  317.  
  318.                 case 'q':
  319.                 case 'Q':
  320.                     xflag = 1;
  321.                     break;
  322.  
  323.                 case 'd':
  324.                 case 'D':
  325.                     xflag = 2;
  326.                     break;
  327.  
  328.                 case 'e':
  329.                 case 'E':
  330.                     return(1);
  331.  
  332.                 case 'n':
  333.                 case 'N':
  334.                     pflag = 0;
  335.                     break;
  336.  
  337.                 case 'p':
  338.                 case 'P':
  339.                     pflag = 1;
  340.                     break;
  341.  
  342.                 case 'b':
  343.                 case 'B':
  344.                     bassav();
  345.                     return(0);
  346.  
  347.                 case 'g':
  348.                 case 'G':
  349.                     gblsav();
  350.                     return(0);
  351.  
  352.                 default:
  353.                     fprintf(stderr, "Invalid option\n");
  354.                     exit(1);
  355.                 }
  356.             }
  357.         } else
  358.         if (ctype[c] & (LETTER|DIGIT)) {
  359.             if (linkp == NULL) {
  360.                 linkp = (struct lfile *)
  361.                     new (sizeof (struct lfile));
  362.                 lfp = linkp;
  363.             } else {
  364.                 lfp->f_flp = (struct lfile *)
  365.                         new (sizeof (struct lfile));
  366.                 lfp = lfp->f_flp;
  367.             }
  368.             getfid(fid, c);
  369.             lfp->f_idp = (char *) new (strlen(fid)+1);
  370.             strcpy(lfp->f_idp, fid);
  371.             lfp->f_type = F_REL;
  372.         } else
  373.         if (c == ';') {
  374.             return(0);
  375.         } else
  376.         if (c == ',') {
  377.             ;
  378.         } else {
  379.             fprintf(stderr, "Invalid input");
  380.             exit(1);
  381.         }
  382.     }
  383.     return(0);
  384. }
  385.  
  386. /*
  387.  * Base string save
  388.  */
  389. VOID
  390. bassav()
  391. {
  392.     if (basep == NULL) {
  393.         basep = (struct base *)
  394.             new (sizeof (struct base));
  395.         bsp = basep;
  396.     } else {
  397.         bsp->b_base = (struct base *)
  398.                 new (sizeof (struct base));
  399.         bsp = bsp->b_base;
  400.     }
  401.     unget(getnb());
  402.     bsp->b_strp = (char *) new (strlen(ip)+1);
  403.     strcpy(bsp->b_strp, ip);
  404. }
  405.     
  406. VOID
  407. setbas()
  408. {
  409.     register v;
  410.     char id[NCPS];
  411.  
  412.     bsp = basep;
  413.     while (bsp) {
  414.         ip = bsp->b_strp;
  415.         getid(id, -1);
  416.         if (getnb() == '=') {
  417.             v = expr(0);
  418.             for (ap = areap; ap != NULL; ap = ap->a_ap) {
  419.                 if (symeq(id, ap->a_id))
  420.                     break;
  421.             }
  422.             if (ap == NULL) {
  423.                 fprintf(stderr,
  424.                 "No definition of area %s\n", id);
  425.             } else {
  426.                 ap->a_addr = v;
  427.             }
  428.         } else {
  429.             fprintf(stderr, "No '=' in base expression");
  430.         }
  431.         bsp = bsp->b_base;
  432.     }
  433. }
  434.  
  435. /*
  436.  * Global string save
  437.  */
  438. VOID
  439. gblsav()
  440. {
  441.     if (globlp == NULL) {
  442.         globlp = (struct globl *)
  443.             new (sizeof (struct globl));
  444.         gsp = globlp;
  445.     } else {
  446.         gsp->g_globl = (struct globl *)
  447.                 new (sizeof (struct globl));
  448.         gsp = gsp->g_globl;
  449.     }
  450.     unget(getnb());
  451.     gsp->g_strp = (char *) new (strlen(ip)+1);
  452.     strcpy(gsp->g_strp, ip);
  453. }
  454.     
  455. VOID
  456. setgbl()
  457. {
  458.     register v;
  459.     register struct sym *sp;
  460.     char id[NCPS];
  461.  
  462.     gsp = globlp;
  463.     while (gsp) {
  464.         ip = gsp->g_strp;
  465.         getid(id, -1);
  466.         if (getnb() == '=') {
  467.             v = expr(0);
  468.             sp = lkpsym(id, 0);
  469.             if (sp == NULL) {
  470.                 fprintf(stderr,
  471.                 "No definition of symbol %s\n", id);
  472.             } else {
  473.                 if (sp->s_flag & S_DEF) {
  474.                     fprintf(stderr,
  475.                     "Redefinition of symbol %s\n", id);
  476.                     sp->s_axp = NULL;
  477.                 }
  478.                 sp->s_addr = v;
  479.                 sp->s_type |= S_DEF;
  480.             }
  481.         } else {
  482.             fprintf(stderr, "No '=' in global expression");
  483.         }
  484.         gsp = gsp->g_globl;
  485.     }
  486. }
  487.  
  488. FILE *
  489. afile(fn, ft, wf)
  490. char *fn;
  491. char *ft;
  492. {
  493.     register char *p1, *p2, *p3;
  494.     register c;
  495.     FILE *fp;
  496.     char fb[FILSPC];
  497.  
  498.     p1 = fn;
  499.     p2 = fb;
  500.     p3 = ft;
  501.     while ((c = *p1++) != 0 && c != FSEPX) {
  502.         if (p2 < &fb[FILSPC-4])
  503.             *p2++ = c;
  504.     }
  505.     *p2++ = FSEPX;
  506.     if (*p3 == 0) {
  507.         if (c == FSEPX) {
  508.             p3 = p1;
  509.         } else {
  510.             p3 = "REL";
  511.         }
  512.     }
  513.     while ((c = *p3++) != 0) {
  514.         if (p2 < &fb[FILSPC-1])
  515.             *p2++ = c;
  516.     }
  517.     *p2++ = 0;
  518.     if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
  519.         fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
  520.         exit(1);
  521.     }
  522.     return (fp);
  523. }
  524.  
  525. char *usetxt[] = {
  526.     "Startup:",
  527.     "  -c                           Command line input",
  528.     "  -f   file[LNK]               File input",
  529.     "Usage: [-Options] file [file ...]",
  530.     "  -p   Prompt and echo of file[LNK] to stdout (default)",
  531.     "  -n   No echo of file[LNK] to stdout",
  532.     "Relocation:",
  533.     "  -b   area base address = expression",
  534.     "  -g   global symbol = expression",
  535.     "Map format:",
  536.     "  -m   Map output generated as file[MAP]",
  537.     "  -x   Hexidecimal (default)",
  538.     "  -d   Decimal",
  539.     "  -q   Octal",
  540.     "Output:",
  541.     "  -i   Intel Hex as file[IHX]",
  542.     "  -s   Motorola S19 as file[S19]",
  543.     "End:",
  544.     "  -e   or null line terminates input",
  545.     "",
  546.     0
  547. };
  548.  
  549. VOID
  550. usage()
  551. {
  552.     register char    **dp;
  553.  
  554.     fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
  555.     for (dp = usetxt; *dp; dp++)
  556.         fprintf(stderr, "%s\n", *dp);
  557.     exit(1);
  558. }
  559.